package genetica.cruce;

import genetica.cromosomas.Cromosoma;
import genetica.cromosomas.genes.Gen;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

public class CrucePMX extends AlgoritmoCruce {

	public CrucePMX(double pCruce) {
		super(pCruce);
	}

	@Override
	public void cruce(Cromosoma prog1, Cromosoma prog2) {
		Random generador = new Random();
		int posCruce1 = (generador.nextInt(prog1.getGenes().size()));
		int posCruce2 = (generador.nextInt(prog1.getGenes().size()));
		if(posCruce1 > posCruce2){
			int temp = posCruce1;
			posCruce1 = posCruce2;
			posCruce2 = temp;
		}
		// Descendientes
		Gen[] desc1 = new Gen[prog1.getGenes().size()];
		Gen[] desc2 = new Gen[prog1.getGenes().size()];
		// ArrayList<Gen> desc1 = new ArrayList<Gen>();
		// ArrayList<Gen> desc2 = new ArrayList<Gen>(prog1.getGenes().size());

		// Arrays de parejas fijas
		// Gen[] fijosProg1 = new Gen[prog1.getGenes().size()];
		// Gen[] fijosProg2 = new Gen[prog1.getGenes().size()];
		ArrayList<Gen> fijosProg1 = new ArrayList<Gen>(prog1.getGenes().size());
		ArrayList<Gen> fijosProg2 = new ArrayList<Gen>(prog1.getGenes().size());

		// Intercambio de las posiciones dentro del intervalo
		for (int i = posCruce1; i < posCruce2; i++) {
			desc1[i] = prog2.getGenes().get(i);
			desc2[i] = prog1.getGenes().get(i);
			// desc1.set(i, prog2.getGenes().get(i));
			// desc2.set(i, prog1.getGenes().get(i));
			// fijosProg1[i] = (prog2.getGenes().get(i));
			// fijosProg2[i] = (prog1.getGenes().get(i));
			fijosProg1.add((prog2.getGenes().get(i)));
			fijosProg2.add((prog1.getGenes().get(i)));
		}

		for (int i = 0; i < prog1.getGenes().size(); i++) {

			// Se eliminan los repetidos fuera del intervalo
			if (i < posCruce1 || i >= posCruce2) {

				// Si un valor no está en la subcadena
				// intercambiada, se copia igual
				// Si está, se sustituye por el valor que tenga dicha
				// subcadena en el otro padre.

				Gen aux = prog1.getGenes().get(i);
				while (fijosProg1.contains(aux))
					aux = prog1.getGenes().get((prog2.getGenes().indexOf(aux)));
				desc1[i] = aux;

				aux = prog2.getGenes().get(i);

				while (fijosProg2.contains(aux))
					aux = prog2.getGenes().get((prog1.getGenes().indexOf(aux)));

				desc2[i] = aux;
			}
		}

		prog1.setGenes(new ArrayList<Gen>(Arrays.asList(desc1)));
		prog2.setGenes(new ArrayList<Gen>(Arrays.asList(desc2)));

		// y sustituyen a los padres
		/*
		 * prog1.evalua());
		 * 
		 * prog2.evalua());
		 */
	}

	@Override
	public String toString() {
		return "Algoritmo de cruce PMX";
	}

}
